from datetime import datetime
from typing import Tuple, Optional
from schemas.response import Response
from core.models import WeeklyReportTimeLimit


class DateValidator:
    """日期验证器类，用于验证和处理日期范围"""

    @staticmethod
    async def is_today_in_time_limit(current_time: datetime) -> bool:
        current_time = current_time.replace(tzinfo=None)
        current_date = current_time.date()
        time_limits = (
            await WeeklyReportTimeLimit.all()
            .order_by("-start_time_limit")
            .limit(10)
            .values("start_time_limit", "end_time_limit")
        )
        for limit in time_limits:
            start_time_limit = limit["start_time_limit"].replace(tzinfo=None)
            end_time_limit = limit["end_time_limit"].replace(tzinfo=None)

            if current_date == start_time_limit.date():
                return True
            if current_date == end_time_limit.date():
                return current_time <= end_time_limit
            if start_time_limit < current_time < end_time_limit:
                return True
        return False

    @staticmethod
    def get_today_end() -> datetime:
        """获取今天的结束时间（23:59:59.999999）"""
        return datetime.now().replace(hour=23, minute=59, second=59, microsecond=999999)

    @staticmethod
    def parse_date_string(date_str: str, field_name: str = "日期") -> datetime:
        """
        解析日期字符串

        Args:
            date_str: 日期字符串，格式：YYYY-MM-DD
            field_name: 字段名称，用于错误提示

        Returns:
            datetime: 解析后的日期对象

        Raises:
            ValueError: 日期格式错误时抛出异常
        """
        try:
            return datetime.strptime(date_str, "%Y-%m-%d")
        except ValueError as e:
            raise ValueError(f"{field_name}格式错误，请使用YYYY-MM-DD格式: {str(e)}")

    @classmethod
    def validate_date_range(
        cls, start_date: str, end_date: str
    ) -> Tuple[Optional[Response], Optional[datetime], Optional[datetime]]:
        """
        验证日期范围并返回处理后的日期

        Args:
            start_date: 开始日期字符串
            end_date: 结束日期字符串

        Returns:
            tuple: (错误响应或None, 开始日期, 结束日期)
        """
        try:
            # 解析日期
            start_dt = cls.parse_date_string(start_date, "开始日期")
            end_dt = cls.parse_date_string(end_date, "结束日期")
        except ValueError as e:
            return Response.fail(code=400, message=str(e)), None, None

        # 获取今天的结束时间
        today = cls.get_today_end()

        # 验证开始日期不能大于结束日期
        if start_dt > end_dt:
            return (
                Response.fail(code=400, message="开始日期不能大于结束日期"),
                None,
                None,
            )

        # 验证开始日期不能大于今天
        if start_dt > today:
            return (
                Response.fail(code=400, message="开始日期不能大于今天的日期"),
                None,
                None,
            )

        return None, start_dt, end_dt

    @classmethod
    def validate_date_list(
        cls, date_list: list
    ) -> Tuple[Optional[Response], Optional[datetime], Optional[datetime]]:
        """
        验证日期列表（通常包含两个元素：开始日期和结束日期）

        Args:
            date_list: 包含开始日期和结束日期的列表

        Returns:
            tuple: (错误响应或None, 开始日期, 结束日期)
        """
        if not date_list or len(date_list) != 2:
            return (
                Response.fail(code=400, message="日期列表必须包含开始日期和结束日期"),
                None,
                None,
            )

        return cls.validate_date_range(date_list[0], date_list[1])
